#ifndef __TOKENIZER_H__
#define __TOKENIZER_H__

#include "rstring.h"
#include "redobject.h"

typedef enum _token_type_t
{
	tk_float,
	tk_string,
	tk_keyword,
	tk_integer,
	tk_operator,
	tk_identifier,
} token_type_t;

typedef enum _tokenizer_error_t
{
	tke_ok,
	tke_eof,
	tke_inv_op,
	tke_inv_char,
	tke_inv_float,
} tokenizer_error_t;

typedef struct _token_t
{
	int				ref;
	token_type_t	token;

	int				int_value;
	float			float_value;
	rstring_t	   *string_value;
} token_t;

typedef struct _tokenizer_t
{
	int					 x;
	int					 y;
	int					 pos;
	token_t				*cache;
	rstring_t			*buffer;

	char		   		 error_char;
	tokenizer_error_t	 error_code;
} tokenizer_t;

RED_EXPORT void token_ref(token_t *self);
RED_EXPORT void token_unref(token_t *self);
RED_EXPORT void token_release(token_t **self);

RED_EXPORT void tokenizer_free(tokenizer_t *self);
RED_EXPORT void tokenizer_init(tokenizer_t *self);
RED_EXPORT void tokenizer_set_source(tokenizer_t *self, rstring_t *source);

RED_EXPORT token_t *tokenizer_peek(tokenizer_t *self);
RED_EXPORT token_t *tokenizer_next(tokenizer_t *self);

static inline const char *token_typename(token_type_t type)
{
	switch (type)
	{
		case tk_float:			return "float";
		case tk_string:			return "string";
		case tk_keyword:		return "keyword";
		case tk_integer:		return "integer";
		case tk_operator:		return "operator";
		case tk_identifier:		return "identifier";
		default:				return "<unknown>";
	}
}

#endif /* __TOKENIZER_H__ */
